
const CALL_DELEGATE = function (...args) {
  this.call = this._createCall('sync')
  return this.call(...args)
}
const CALL_ASYNC_DELEGATE = function (...args) {
  this.call = this._createCall('async');
  return this.call(...args)
}
const PROMISE_DELEGATE = function (...args) {
  this.promise = this._createCall('promise');
  return this.promise(...args)
}

class Hook {
  constructor(args = []) {
    this.args = args;//['name', 'age'];
    this.taps = []; // 存放时间函数处理后的对象，{name,fn}
    this._x = undefined; // 真正存放时间函数的数组[fn,fn1,fn2]
    this.call = CALL_DELEGATE;
    this.callAsync = CALL_ASYNC_DELEGATE;
    this.promise = PROMISE_DELEGATE
  }
  // tap 传递连个参数，事件名，一个函数 hook.tap('1',(name,age) =>{})
  tap(options, fn) {
    this._tap('sync', options, fn)
  }
  tapAsync(options, fn) {
    this._tap('async', options, fn)
  }
  tapPromise(options, fn) {
    this._tap('promise', options, fn)
  }
  _tap(type, options, fn) {
    if (typeof options === 'string') {
      options = { name: options }
    }
    let tapInfo = { ...options, fn, type }
    this._insert(tapInfo)
  }

  _resetCompilation() {
    this.call = CALL_DELEGATE;
  }
  compile() {
    throw new Error("Abstract: should be overridden")
  }
  _createCall(type) {
    return this.compile({
      taps: this.taps,
      args: this.args,
      type
    })
  }
  _insert(tapInfo) {
    // 为了保证每次tap或者tapAsync后，调用call，会生成新的执行代码，每次插入时都要将call重置为初始化状态，使可以生成新的函数代码
    this._resetCompilation()
    this.taps.push(tapInfo)
  }
}

module.exports = Hook